package com.softserveinc.moviedbapp.playa;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.softserveinc.moviedbapp.R;

import java.io.IOException;

public class CustomVideoPlayer extends Activity implements SurfaceHolder.Callback, OnPreparedListener, OnErrorListener,
		OnBufferingUpdateListener, OnCompletionListener {
	private MediaPlayer mMediaPlayer;
	private SurfaceView mPreview;
	private SurfaceHolder mHolder;
	private String mVideoPath;

	/* indicates the state of the player */
	enum State {
		Retrieving, Stopped, Preparing, Playing, Paused
	};

	State mPlayerState = State.Retrieving;

	private static final String TAG = CustomVideoPlayer.class.getSimpleName();

	/** Called when the activity is first created. */
	@Override
	public void onCreate(final Bundle savedInstanceState) {

		setTheme(android.R.style.Theme_Black);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.video);

		Log.d(TAG, "onCreate()");
		mVideoPath = getIntent().getDataString();

		Log.i(TAG, "WANTED TO PLAY " + mVideoPath);
		initElements();
	}

	@Override
	protected void onPause() {
		super.onPause();
		releaseMediaPlayer();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		releaseMediaPlayer();
	}

	@Override
	public boolean onCreateOptionsMenu(final Menu menu) {
		getMenuInflater().inflate(R.menu.menu_video, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_play:
			startPlayback();
			return true;

		case R.id.menu_pause:
			pausePlayback();
			return true;

		case R.id.menu_stop:
			stopPlayback();
			return true;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public void surfaceCreated(final SurfaceHolder holder) {
		initPlayer();
	}

	@Override
	public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {
		// TODO Auto-generated method stub
	}

	@Override
	public void surfaceDestroyed(final SurfaceHolder holder) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onPrepared(final MediaPlayer mp) {

		Log.d(TAG, "onPrepared()");
		mHolder.setFixedSize(getWindow().getWindowManager().getDefaultDisplay().getWidth(), getWindow()
				.getWindowManager().getDefaultDisplay().getHeight());
		Log.d(TAG, "mMediaPlayer.start();");

		mPlayerState = State.Paused;
		startPlayback();
	}

	@Override
	public boolean onError(final MediaPlayer mp, final int what, final int extra) {

		if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
			Log.e(TAG, "onError() MEDIA_ERROR_UNKNOWN");
			Log.e(TAG, "Resource path = " + mVideoPath);

			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage(R.string.cant_play_video)
					.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

						@Override
						public void onClick(final DialogInterface dialog, final int which) {
							Intent i = new Intent(Intent.ACTION_VIEW);
							i.setData(Uri.parse(mVideoPath));
							startActivity(i);
							dialog.dismiss();
							finish();
						}

					}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

						@Override
						public void onClick(final DialogInterface dialog, final int which) {
							finish();

						}

					}).setCancelable(false).create().show();

		} else {
			Log.e(TAG, "onError() MEDIA_ERROR_SERVER_DIED");
		}

		mp.reset();
		return true;
	}

	@Override
	public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
		Log.d(TAG, "onBufferingUpdate percent:" + percent);

	}

	@Override
	public void onCompletion(final MediaPlayer mp) {
		Log.d(TAG, "Video finished playing");
		mp.reset();
	}

	private void initElements() {

		Log.d(TAG, "initElements()");

		mPreview = (SurfaceView) findViewById(R.id.surface_video);

		mHolder = mPreview.getHolder();

		/* without this line nothing will show up */
		mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

		Log.d(TAG, "holder.addCallback(this);");
		mHolder.addCallback(this);

		mMediaPlayer = new MediaPlayer();

		mMediaPlayer.setDisplay(mHolder);

		mMediaPlayer.setOnErrorListener(this);

		Log.d(TAG, "mMediaPlayer.setOnPreparedListener(this);");
		mMediaPlayer.setOnPreparedListener(this);
	}

	private void initPlayer() {
		Log.d(TAG, "initPlayer()");

		try {

			mMediaPlayer.setDataSource(mVideoPath);
			Log.d(TAG, "DATA SOURCE SET TO " + mVideoPath);
			mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

			Log.d(TAG, "prepareAsync() ");
			mMediaPlayer.prepareAsync();

			mPlayerState = State.Preparing;

		} catch (IllegalArgumentException e) {

			Log.e(TAG, "initPlayer() IllegalArgumentException", e);

		} catch (IllegalStateException e) {

			Log.e(TAG, "initPlayer() IllegalStateException", e);

		} catch (IOException e) {

			Log.e(TAG, "initPlayer() IOException", e);

		}

	}

	private void releaseMediaPlayer() {
		if (mMediaPlayer != null) {
			Log.d(TAG, "releasing media player...");
			mMediaPlayer.release();
			mMediaPlayer = null;
		}
		mPlayerState = State.Retrieving;
	}

	private void pausePlayback() {
		if (mPlayerState.equals(State.Playing)) {
			Log.d(TAG, "pausing media player...");
			mMediaPlayer.pause();
			mPlayerState = State.Paused;
		}
	}

	private void startPlayback() {
		if (mPlayerState.equals(State.Retrieving)) {
			Log.d(TAG, "re-init media player...");
			initPlayer();
		} else if (mPlayerState.equals(State.Paused)) {
			Log.d(TAG, "starting media player after pausing...");
			mMediaPlayer.start();
			mPlayerState = State.Playing;
		}
	}

	private void stopPlayback() {
		if (mPlayerState.equals(State.Playing) || mPlayerState.equals(State.Paused)) {
			Log.d(TAG, "stopping media player...");
			mMediaPlayer.stop();
			mPlayerState = State.Stopped;
			resetPlayer();
		}
	}

	private void resetPlayer() {
		Log.d(TAG, "resetting media player...");
		mPlayerState = State.Retrieving;
		mMediaPlayer.reset();
	}

}